﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

/// <summary>
/// 玩家角色
/// </summary>
public class Player : StateMachineComponent<System.Type>,Damageable
{
    public enum Characters{
        // 比尔
        BillRizer,
        // 兰斯
        LanceBean,
    }

    // 角色使用的人物
    public Characters characters=Characters.BillRizer;

    //移动速度(60帧移动了60个像素)
    //speed=(60像素)/(16像素/单位)*(60帧/秒)/(60帧)=3.75单位/秒    
    internal float speed = 60f / 16f * 60f / 60f;

    /**
     * 跳跃初速度，跳跃高度61像素，用时30帧
     * s=61÷16=3.8125
     * t=30÷60=0.5
     * Vt=2×s÷t=15.25  
     * a=Vt÷t=4×s÷t=30.5
     * Gravity Scale=30.5÷9.81=3.109072375127421
     */
    internal float jumpSpeed = 2 * (61f / 16f) / (30f / 60f);
    internal float gravityScale = 4 * (61f / 16f) / (30f / 60f)/9.81f;

    //WSAD按键值
    internal float axisX, axisY;
    //是否按下了按键 开枪
    internal bool firePressed, jumpPressed;

    //是否站在地面
    internal bool onGround;
    //是否在水面上
    internal bool onWater;

    //记录按键的方向
    internal Vector2 keyDirection = Vector2.zero;

    //记录比尔面朝的方向，默认面朝右侧
    internal Vector2 lookAt = Vector2.right;
    internal Vector2 velocity = Vector2.zero;

    //解决开枪抖动
    //记录上一次的开枪时间
    internal float lastFireTime = -1;
    //设定开枪的持续时间(通过模拟器测量，开枪姿势保持16帧)
    internal readonly float firePostureKeepingTime = 16f / 60f;

    // 隐身状态
    internal bool avoiding=false;
    // 在模拟器中测量，隐身持续126帧，每1帧进行闪烁(但这样效果不好，改为2帧闪烁更顺畅)
    internal SeqAction avoidAction=new (){intervalTime=2f/60f,keepingTime=126f/60};

    //上一个状态
    internal System.Type lastPosture = default;

    //定义刚体组件
    internal Rigidbody2D rig;

    //定义动画组件
    internal Animator animator;

    //上半身
    internal GameObject upperBody;
    //下半身
    internal GameObject lowerBody;
    //卧倒
    internal GameObject lieDownBody;
    //跳跃翻滚
    internal GameObject rollBody;
    //下落
    internal GameObject fallBody;
    //水花
    internal GameObject splashBody;
    //下水
    internal GameObject inWaterBody;
    //潜水
    internal GameObject hideInWaterBody;
    //上岸
    internal GameObject goAshoreBody;
    //死亡
    internal GameObject dieBody;
    internal GameObject dieRollBody;
    internal GameObject dieLiedownBody;

    //平台碰撞体
    internal GameObject groundCheckBody;

    internal GameObject[] bodys;

    internal int health=1;

    public int Health {
        get{
            return this.health;
        }
        set{
            this.health=value;
        }
    }

    // 玩家剩余生命
    internal int life=3;
    public int Life{get{return this.life;}}

    [Tooltip("跟随角色的摄像机")]
    public Camera followCamera;

    /// <summary>
    /// 取得最近的玩家对象
    /// </summary>
    /// <param name="point">测距的原点</param>
    /// <param name="nearestPlayerPosition">找到的最近的位置</param>
    /// <returns></returns>
    public static bool GetNearestPlayerPosition(Vector2 point, out Vector2 nearestPlayerPosition)
    {
       IEnumerable<Vector2> playersPosition = GameObject.FindObjectsOfType<Player>().Transform((Player player) =>
       {
            Vector2 ret=player.transform.position;
           return ret;
       });
       return Utility.Nearest(playersPosition, point, out nearestPlayerPosition);
    }


    // 当前场景中存活的玩家角色
    public static Player[] GetAlivePlayersInScene(){
        return GameObject.FindObjectsOfType<Player>().Filter((Player player)=>{
            return player.Life > 0;
        }).ToArray();
    }

    void Awake()
    {
        if(followCamera==null){
            followCamera=Camera.main;
        }

        // 取得刚体组件对象，只执行一次
        rig = GetComponent<Rigidbody2D>();

        //取得动画组件对象
        animator = GetComponent<Animator>();

        //初始化身体部件
        bodys = new GameObject[]
        {
            upperBody=transform.Find("上半身").gameObject,
            lowerBody=transform.Find("下半身").gameObject,
            lieDownBody = transform.Find("卧倒").gameObject,
            rollBody = transform.Find("翻滚").gameObject,
            fallBody=transform.Find("下落").gameObject,
            splashBody=transform.Find("水花").gameObject,
            inWaterBody=transform.Find("下水").gameObject,
            hideInWaterBody=transform.Find("潜水").gameObject,
            goAshoreBody=transform.Find("上岸").gameObject,
            dieBody=transform.Find("死亡").gameObject,
        };
        dieRollBody=dieBody.transform.Find("死亡-翻滚").gameObject;
        dieLiedownBody=dieBody.transform.Find("死亡-平躺").gameObject;
        groundCheckBody=transform.Find("平台碰撞体").gameObject;

        //重力加速度
        rig.gravityScale = gravityScale;

        InitStateActions();

        UpdatePosture();


    }


    protected override void Update()
    {
        //取得按键
        axisX = Input.GetAxisRaw("Horizontal");
        axisY = Input.GetAxisRaw("Vertical");
        
        // 如果此时 firePressed==true 表示上一次在Update函数中接收到的按键还没有处理，
        // 所以需要保留当下的状态，否则会出现按键偶尔失灵的现象
        // jumpPressed同理
        firePressed = firePressed || Input.GetButtonDown("Fire1");
        jumpPressed = jumpPressed || Input.GetButtonDown("Jump");

        base.Update();

        //设置按键方向
        keyDirection.x = axisX > 0 ? 1 : (axisX < 0 ? -1 : 0);
        keyDirection.y = axisY > 0 ? 1 : (axisY < 0 ? -1 : 0);

        //按左键面朝左，按右键面朝右，不按键保持当前朝向
        if (keyDirection.x < 0)
        {
            lookAt.x = -1;
        }
        else if (keyDirection.x > 0)
        {
            lookAt.x = 1;
        }
        lookAt.y = keyDirection.y;

        //每次开枪刷新开枪时间
        if (firePressed)
        {
            lastFireTime = Time.time;
        }

        UpdateAnimator();
        UpdatePosture();


    }

    protected override void FixedUpdate()
    {
        /** 
         * 检查是否站在地面上
         * 从角色当前位置的脚下(transform.position),向下(Vector3.down)发射一条长度为(0.1)的射线，判断是否与跳台层(Constant.Layers.GroundLayer)发生了碰撞
        */
        onGround = CheckOnGround(Constant.Layers.GroundLayer); 
        if(!onGround){
            onWater = CheckOnGround(Constant.Layers.WaterLayer);
        }else{
            onWater=false;
        }

        //根据朝向，改变Transform的Scale属性，只考虑X轴
        Vector2 scale = transform.localScale;
        scale.x = lookAt.x;
        transform.localScale = scale;

        //计算刚体速度
        velocity = new Vector2(speed * keyDirection.x, rig.velocity.y);

        base.FixedUpdate();

        //设置刚体速度
        rig.velocity = velocity;

        //发射子弹
        if(firePressed){
            Fire();
        }

        // 在处理完firePressed和jumpPressed需要设置为false,否则会持续开枪和跳跃
        firePressed = jumpPressed = false;

        // 限制角色移动不能超出镜头边界
        UpdateInViewport();
        // 隐身状态
        UpdateAvoiding();
    }

    void UpdateAnimator()
    {
        animator.SetBool("Run", keyDirection.x != 0);
        animator.SetFloat("X", keyDirection.x);
        animator.SetFloat("Y", keyDirection.y);

        //在设定的时间范围内，保持开枪姿势
        animator.SetBool("KeepFire", Time.time - lastFireTime <= firePostureKeepingTime);
        if (firePressed)
        {
            animator.SetTrigger("Fire");
        }

        animator.SetBool("Jump", state == typeof(PlayerStateAction_Roll));
        animator.SetBool("InWater", state == typeof(PlayerStateAction_InWater)||state == typeof(PlayerStateAction_HideInWater));

        if(lastPosture!=typeof(PlayerStateAction_GoAshore) && state==typeof(PlayerStateAction_GoAshore)){
            animator.SetTrigger("GoAshore");
        }
    }
    
    // 限制角色移动不能超出镜头边界
    void UpdateInViewport()
    {
        float left = followCamera.ViewportToWorldPoint(Vector3.zero).x + 1.5f;
        float right = followCamera.ViewportToWorldPoint(Vector3.right).x - 1.5f;
        Vector3 position = transform.position;

        //不允许人物移动超出摄像头的左右边界
        if (position.x < left)
        {
            position.x = left;
        }

        if (position.x > right)
        {
            position.x = right;
        }

        transform.position = position;
    }

    // 隐身状态
    void UpdateAvoiding(){
        if(!avoiding && avoidAction.done){
            avoidAction.Clear();
        }
        if(avoiding){
            avoidAction.Update((SeqAction seq)=>{
                int index=seq.seqNo%2;
                SpriteMaskInteraction v=index==0?SpriteMaskInteraction.None:SpriteMaskInteraction.VisibleInsideMask;
                bodys.Foreach((GameObject go)=>{
                    if(go.TryGetComponent(out SpriteRenderer renderer)){
                        renderer.maskInteraction=v;
                    }
                });
            });
            if(avoidAction.done){
                bodys.Foreach((GameObject go)=>{
                    if(go.TryGetComponent(out SpriteRenderer renderer)){
                        renderer.maskInteraction=SpriteMaskInteraction.None;
                    }
                });
            }
        }

        if(avoiding && avoidAction.done){
            avoiding=false;
        }
    }
    void UpdatePosture()
    {
        //状态不改变不会重复执行
        if (state != lastPosture)
        {
            //当前状态下该显示哪些身体部件
            HashSet<GameObject> activeBodys = new();
            if(stateMachine.TryGetState(state,out IStateAction<System.Type> stateAction)){
                if(stateAction is PlayerStateAction){
                    PlayerStateAction playerStateAction=stateAction as PlayerStateAction;
                    if(playerStateAction.activeBodys!=null){
                        playerStateAction.activeBodys.Foreach((GameObject go)=>{
                            activeBodys.Add(go);
                        });
                    }
                }
            }
            if(activeBodys.Empty())
            {
                activeBodys.Add(upperBody);
                activeBodys.Add(lowerBody);
            }
            

            //设置身体部件是否可显示
            foreach (GameObject body in bodys)
            {
                if (activeBodys.Contains(body))
                {
                    body.SetActive(true);
                }
                else
                {
                    body.SetActive(false);
                }
            }
            //保存当前状态
            lastPosture = state;
        }
    }


    void InitStateActions()
    {
        state=typeof(PlayerStateAction_Normal);
        stateMachine.Registe(new PlayerStateAction[] {
            new PlayerStateAction_Normal(this),
            new PlayerStateAction_LieDown(this),
            new PlayerStateAction_Roll(this),
            new PlayerStateAction_Fall(this),
            new PlayerStateAction_Splash(this),
            new PlayerStateAction_InWater(this),
            new PlayerStateAction_HideInWater(this),
            new PlayerStateAction_GoAshore(this),
            new PlayerStateAction_Die(this),
        });
    }

    public void AnimationEvent_GoAshoreDone(){
        Vector3 position=transform.position;
        position.x+=lookAt.x*(5f/16f);
        position.y+=8f/16f;
        transform.position=position;
        state=typeof(PlayerStateAction_Fall);
    }

    bool CheckOnGround(LayerMask layers){
        bool ret=false;
        if(groundCheckBody.TryGetComponent(out Collider2D collider))
        {
            Bounds bounds=collider.bounds;
            Vector2[] startPoints=new Vector2[]{
                new(bounds.min.x,bounds.min.y),
                new(bounds.max.x,bounds.min.y),
            };
            startPoints.Foreach((Vector2 startPoint,ref bool _break)=>{
                RaycastHit2D _hit=Physics2D.Raycast(startPoint,Vector2.down,0.0625f,layers);
                if(_hit){
                    ret=true;
                    _break=true;
                }
            });
        };
        return ret;
    }
    
    /// <summary>
    /// 发射子弹
    /// </summary>
    void Fire(){
        // 取得枪口位置和子弹飞行方向
        BulletMeta bulletMeta= PlayerMuzzle.GetMuzzle(this);
        if(bulletMeta!=null){
            // 通过子弹的预制件创建子弹对象
            GameObject bulletObj=Instantiate(Constant.Prefabs.BulletC.Load(),bulletMeta.sourcePoint,Quaternion.identity);
            if(bulletObj.TryGetComponent(out Bullet bullet)){
                // 让子弹飞行
                bullet.Launch(bulletMeta);
            }
        }
    }

    /// <summary>
    /// 受到伤害
    /// </summary>
    /// <param name="damageSource">伤害来源</param>
    /// <param name="damagePoint">伤害点</param>
    /// <returns>造成的实际伤害</returns>
    public int Damage(GameObject damageSource,int damagePoint){
        if(avoiding){
            // 隐身状态不受伤害
            return 0;
        }
        int ret=damagePoint;
        this.Health-=damagePoint;
        if(this.Health<=0){
            this.Die();
        }
        if(this.Health<0){
            ret=this.Health+damagePoint;
        }
        return ret;
    }

    private void Die(){
        this.state=typeof(PlayerStateAction_Die);
    }

    // 角色重生
    public void Reborn(){
        // 重生位置在游戏窗口中的位置
        Vector2 rebornPositionInViewport=default;
        switch(characters){
            case Characters.BillRizer:
                rebornPositionInViewport=new Vector2(48f/256f,1f-(24f/224f));
                break;
            case Characters.LanceBean:
                rebornPositionInViewport=new Vector2(32f/256f,1f-(24f/224f));
                break;
            default:
                rebornPositionInViewport=new Vector2(48f/256f,1f-(24f/224f));
                break;

        }
        // 转换为场景坐标
        Vector2 rebornPosition=followCamera.ViewportToWorldPoint(rebornPositionInViewport);
        // 翻滚对象与游戏对象有相对位置
        Vector2 offsetRebornPosition=rollBody.transform.localPosition;
        transform.position=rebornPosition-offsetRebornPosition;
        avoiding=true;
        // 重生后进入翻滚状态
        state=typeof(PlayerStateAction_Roll);
    }
}

/// <summary>
/// 玩家角色状态类的基类
/// </summary>
public abstract class PlayerStateAction : IStateAction<System.Type>
{
    // 状态上下文中的玩家角色对象
    protected Player player;
    // 状态类的状态值
    public System.Type State { get { return this.GetType(); } }
    public GameObject[] activeBodys;

    /// <summary>
    /// 初始化方法
    /// </summary>
    /// <param name="player">玩家对象</param>
    public PlayerStateAction(Player player)
    {
        this.player = player;
    }
    
    public virtual void Enter(System.Type lastState, System.Type currentState){}
    public virtual void Exit(System.Type currentState, System.Type nextState){}
    public virtual void Update(System.Type inState, out System.Type outState){
        outState=inState;
    }
    public virtual void FixedUpdate(System.Type inState, out System.Type outState){
        outState=inState;
    }
}

/// <summary>
/// 普通状态,站立+跑步
/// </summary>
public class PlayerStateAction_Normal : PlayerStateAction
{
    public PlayerStateAction_Normal(Player player) : base(player) {
        activeBodys=new GameObject[]{
            player.upperBody,
            player.lowerBody,
        };
    }

    public override void FixedUpdate(System.Type inState, out System.Type outState)
    {
        base.FixedUpdate(inState,out outState);

        //在正常状态下按跳跃键，开始跳跃
        if (player.jumpPressed)
        {
            player.velocity.y = player.jumpSpeed;
            outState = typeof(PlayerStateAction_Roll);
        }
        //正常状态时，判断是否应该卧倒
        else if (player.onGround && player.keyDirection.x == 0 && player.keyDirection.y < 0)
        {
            outState = typeof(PlayerStateAction_LieDown);
        }
        //不站在地面上则会下落
        else if(!player.onGround){
            outState=typeof(PlayerStateAction_Fall);
        }
    }
}

/// <summary>
/// 卧倒状态
/// </summary>
public class PlayerStateAction_LieDown : PlayerStateAction
{
    public PlayerStateAction_LieDown(Player player) : base(player) { 
        activeBodys=new GameObject[]{
            player.lieDownBody,
        };
    }

    public override void FixedUpdate(System.Type inState, out System.Type outState)
    {
        base.FixedUpdate(inState,out outState);

        //卧倒状态下不能左右移动
        player.velocity.x = 0f;

        //卧倒状态时，判断是否应该站立
        if (player.keyDirection.y >= 0 || player.keyDirection.x!=0f)
        {
            outState = typeof(PlayerStateAction_Normal);
        }
        // 从平台下落
        else if(player.jumpPressed){
            //判断下落后是否有平台或水面可以着陆
            Vector3 position=player.transform.position;
            Vector2 cameraSize=Utility.CameraSize(Camera.main);
            RaycastHit2D hit=Physics2D.Raycast(position+Vector3.down,Vector2.down,cameraSize.y,Constant.Layers.GroundAndWaterLayer);
            if(hit){
                position.y-=3f/16f;
                player.transform.position=position;
                outState=typeof(PlayerStateAction_Fall);
            }
        }

    }
}

/// <summary>
/// 跳跃翻滚状态
/// </summary>
public class PlayerStateAction_Roll : PlayerStateAction
{
    public PlayerStateAction_Roll(Player player) : base(player) {
        activeBodys=new GameObject[]{
            player.rollBody,
        };
    }

    public override void FixedUpdate(System.Type inState, out System.Type outState)
    {
        base.FixedUpdate(inState,out outState);
        //跳跃状态下处理落地和移动
        if (player.onGround && player.rig.velocity.y<=0.001)
        {
            // 跳跃落地
            outState = typeof(PlayerStateAction_Normal);
        }
        else if(player.onWater){
            outState=typeof(PlayerStateAction_Splash);
        }
        else
        {
            float currentSpeed = Mathf.Abs(player.rig.velocity.x);
            // 由于float类型会产生一个非常接近0，但不是0的值。
            // 所以这里通过与一个很小的值比较代替"!=0"的判断
            if (currentSpeed<0.0001)
            {
                //站立状态下起跳，在空中通过方向键可移动
                currentSpeed = player.speed * player.keyDirection.x;
            }
            else
            {
                //跳跃状态下松开方向键仍会移动
                currentSpeed = player.speed*player.lookAt.x;
            }
            player.velocity.x = currentSpeed;
        }

    }
}

/// <summary>
/// 下落状态
/// </summary>
public class PlayerStateAction_Fall : PlayerStateAction
{
    public PlayerStateAction_Fall(Player player) : base(player) {
        activeBodys=new GameObject[]{
            player.fallBody,
        };
    }

    public override void FixedUpdate(System.Type inState, out System.Type outState)
    {
        base.FixedUpdate(inState,out outState);
        //跳跃状态下处理落地和移动
        if (player.onGround)
        {
            // 跳跃落地
            outState = typeof(PlayerStateAction_Normal);
        }
        //落到水上则转换为入水水花状态
        else if(player.onWater){
            outState=typeof(PlayerStateAction_Splash);
        }
    }    
}


/// <summary>
/// 水花状态
/// </summary>
public class PlayerStateAction_Splash : PlayerStateAction
{
    // 用来执行水花持续10帧的效果。
    // 这里时第一次使用SeqAction，它用于简化经常用来在固定时间片中重复执行和计时的逻辑。
    // SeqAction的代码来源自Utility.cs
    private SeqAction splashAction= new() { beginWaitTime = 0f, intervalTime = 0f, keepingTime = 10f / 60f };
    public PlayerStateAction_Splash(Player player) : base(player) { 
        activeBodys=new GameObject[]{
            player.splashBody,
        };
    }

    public override void Enter(Type lastState, Type currentState)
    {
        base.Enter(lastState, currentState);
        splashAction.ReStart();
    }
    public override void FixedUpdate(System.Type inState, out System.Type outState)
    {
        base.FixedUpdate(inState,out outState);
        splashAction.Update((SeqAction seq) =>{});
        if (splashAction.done)
        {
            outState = typeof(PlayerStateAction_InWater);
        }

        player.velocity=Vector2.zero;
     
    }    
}


/// <summary>
/// 下水状态
/// </summary>
public class PlayerStateAction_InWater : PlayerStateAction
{
    public PlayerStateAction_InWater(Player player) : base(player) {
        activeBodys=new GameObject[]{
            player.inWaterBody,
        };
    }

    public override void FixedUpdate(System.Type inState, out System.Type outState)
    {
        base.FixedUpdate(inState,out outState);
        if(player.keyDirection.y<0){
            outState=typeof(PlayerStateAction_HideInWater);
        }else{
            if(player.groundCheckBody.TryGetComponent(out Collider2D collider)){
                Bounds bounds=collider.bounds;
                Vector2[] startPoints;
                if(player.lookAt.x>0){
                    startPoints=new Vector2[]{
                        new(bounds.max.x,bounds.max.y),
                        new(bounds.max.x,bounds.min.y),
                    };
                }else{
                    startPoints=new Vector2[]{
                        new(bounds.min.x,bounds.max.y),
                        new(bounds.min.x,bounds.min.y),
                    };
                }
                bool hit=false;
                startPoints.Foreach((Vector2 startPoint,ref bool _break)=>{
                    RaycastHit2D _hit=Physics2D.Raycast(startPoint,new Vector2(player.lookAt.x,0),0.0625f,Constant.Layers.GroundLayer);
                    if(_hit){
                        hit=true;
                        _break=true;
                    }
                });
                if(player.onGround || hit){
                    outState=typeof(PlayerStateAction_GoAshore);
                }
            }
        }
    }    
}

/// <summary>
/// 潜水状态
/// </summary>
public class PlayerStateAction_HideInWater : PlayerStateAction
{
    public PlayerStateAction_HideInWater(Player player) : base(player) { 
        activeBodys=new GameObject[]{
            player.hideInWaterBody,
        };
    }
    public override void Update(Type inState, out Type outState)
    {
        base.Update(inState, out outState);
        //在潜水状态下不能开枪和移动
        player.firePressed=player.jumpPressed=false;
        player.axisX=0f;
    }

    public override void FixedUpdate(System.Type inState, out System.Type outState)
    {
        base.FixedUpdate(inState,out outState);
        // 松开“下”露出水面
        if(player.keyDirection.y>=0){
            outState=typeof(PlayerStateAction_InWater);
        }
    }
}

/// <summary>
/// 上岸状态
/// </summary>
public class PlayerStateAction_GoAshore : PlayerStateAction
{
    public PlayerStateAction_GoAshore(Player player) : base(player) { 
        activeBodys=new GameObject[]{
            player.goAshoreBody,
        };
    }

    public override void Enter(Type lastState, Type currentState)
    {
        base.Enter(lastState, currentState);
        // 在上岸动作中，取消重力和碰撞体
        // 否则在播放动画时，重力和碰撞会影响位置判断
        player.rig.gravityScale=0;
        player.groundCheckBody.SetActive(false);

    }
    public override void Update(Type inState, out Type outState)
    {
        base.Update(inState, out outState);
        //在上岸状态下不能开枪和移动
        player.firePressed=player.jumpPressed=false;
        player.axisX=player.axisY=0f;

        // 状态主要逻辑在"UpdateAnimator"中触发播放动画
    }

    public override void Exit(Type currentState, Type nextState)
    {
        base.Exit(currentState, nextState);
        // 在上岸动作完成，恢复重力和碰撞体
        player.rig.gravityScale=player.gravityScale;
        player.groundCheckBody.SetActive(true);
    }
}


/// <summary>
/// 死亡状态
/// 死亡有两个动作，翻滚和平躺。
/// 翻滚时，一面做公转（公转轨迹是：长边为19像素，短边14像素的椭圆曲线），一面做自转（每7帧逆时针旋转90度）
/// 翻滚公转180度后，转为平躺状态。
/// 平躺状态下先下落6帧，然后保持平躺64帧，然后所有动作完成
/// </summary>
public class PlayerStateAction_Die : PlayerStateAction
{
    // 保留旋转初始位置
    Vector2 startLocalPosition;
    // 翻滚动作,keepingTime为持续时间
    SeqAction rollAction=new(){keepingTime=30f/60f};
    // 公转角度
    float revolveTotalAngle=180f;
    // 公转椭圆长轴
    float revolveMajorAxisLength=14f/16f;
    // 公转椭圆短轴
    float revolveMinorAxisLength=19f/16f;
    // 公转轴心位置
    Vector2 ellipseCenterLocalPosition;
    // 自转单步间隔时间
    float rotateIntervalTime=7f/60f;
    // 自转单步角度
    float rotateStepAngle=90f;
    // 平躺动作
    SeqAction lieDownAction=new(){keepingTime=(6f+64f)/60f};
    // 平躺下落的时间
    float lieDownFallTime=6f/60f;

    public PlayerStateAction_Die(Player player) : base(player) { 
        activeBodys=new GameObject[]{
            player.dieBody,
        };
    }

    public override void Enter(Type lastState, Type currentState)
    {
        base.Enter(lastState, currentState);
        // 在死亡动作中，取消重力和碰撞体
        player.rig.gravityScale=0;
        player.groundCheckBody.SetActive(false);
        // 初始化是显示翻滚对象，隐藏平躺对象
        player.dieLiedownBody.SetActive(false);
        player.dieRollBody.SetActive(true);
        // 保存初始位置
        startLocalPosition=player.dieRollBody.transform.localPosition;
        // 设置公转圆心
        ellipseCenterLocalPosition=startLocalPosition+new Vector2(-revolveMajorAxisLength,0);
        // 初始化动作对象
        rollAction.Clear();
        lieDownAction.Clear();

    }
    public override void Update(Type inState, out Type outState)
    {
        base.Update(inState, out outState);
        //在死亡状态下不能开枪和移动
        player.firePressed=player.jumpPressed=false;
        player.axisX=player.axisY=0f;
    }
    public override void FixedUpdate(Type inState, out Type outState)
    {
        base.FixedUpdate(inState, out outState);
        // 清除角色移动速度
        player.velocity=Vector2.zero;

        // 由于设置了keepingTime,动作在持续了keepingTime后自动设置done=true
        // done为true时不会调用行为函数
        rollAction.Update((SeqAction seq)=>{
            // 计算当前公转位置
            float revolveAngle=revolveTotalAngle*(seq.DurationTime/seq.keepingTime);
            float offsetX=revolveMajorAxisLength*Mathf.Cos(revolveAngle*Mathf.Deg2Rad);
            float offsetY=revolveMinorAxisLength*Mathf.Sin(revolveAngle*Mathf.Deg2Rad);
            Vector2 localPosition=ellipseCenterLocalPosition+new Vector2(offsetX,offsetY);
            player.dieRollBody.transform.localPosition=localPosition;

            // 计算当前自转角度
            int rotateIndex=Mathf.FloorToInt(seq.DurationTime/rotateIntervalTime);
            float rotateAngle=rotateStepAngle*rotateIndex;
            Quaternion rotation=Quaternion.Euler(0,0,rotateAngle);
            player.dieRollBody.transform.localRotation=rotation;
        });

        // 旋转结束，执行平躺动作
        if(rollAction.done){
            // 隐藏旋转对象，显示平躺对象
            player.dieRollBody.SetActive(false);
            player.dieLiedownBody.SetActive(true);
            // 计算平躺下落的高
            float y=player.dieRollBody.transform.localPosition.y;
            lieDownAction.Update((SeqAction seq)=>{
                if(seq.IsFirstAction()){
                    // 第一次实行时，将平躺对象的位置设置为翻滚对象最后的位置
                    player.dieLiedownBody.transform.localPosition=player.dieRollBody.transform.localPosition;
                }
                // 计算当前平躺对象下落的位置
                float offsetY=y*Mathf.Clamp(seq.DurationTime/lieDownFallTime,0f,1f);
                Vector2 localPosition=player.dieLiedownBody.transform.localPosition;
                localPosition.y=y-offsetY;
                player.dieLiedownBody.transform.localPosition=localPosition;
            });
        }
        if(lieDownAction.done){
            // 死亡状态下所有的动作完成，调用重生函数
            player.Reborn();
        }
    }

    public override void Exit(Type currentState, Type nextState)
    {
        base.Exit(currentState, nextState);
        // 在死亡动作完成，恢复重力和碰撞体
        player.rig.gravityScale=player.gravityScale;
        player.groundCheckBody.SetActive(true);
        // 恢复初始位置和旋转角度
        player.dieRollBody.transform.localPosition=startLocalPosition;
        player.dieRollBody.transform.localRotation=Quaternion.Euler(0,0,0);

    }
}
